/**
 * JSON 差异计算引擎
 * 专门用于计算两个 JSON 对象之间的语义差异
 */

class JSONDiffEngine {
    /**
     * 计算两个 JSON 对象之间的差异
     * @param {Object} obj1 - 第一个 JSON 对象
     * @param {Object} obj2 - 第二个 JSON 对象
     * @param {string} path - 当前路径（内部使用）
     * @returns {Array} 差异数组
     */
    static computeDiff(obj1, obj2, path = '') {
        const diffs = [];
        
        // 处理 null 或 undefined 情况
        if (obj1 === null || obj1 === undefined || obj2 === null || obj2 === undefined) {
            if (obj1 !== obj2) {
                diffs.push({
                    type: 'modified',
                    path: path,
                    oldValue: obj1,
                    newValue: obj2,
                    oldValueType: this.getValueType(obj1),
                    newValueType: this.getValueType(obj2)
                });
            }
            return diffs;
        }
        
        // 获取所有键
        const keys1 = typeof obj1 === 'object' ? Object.keys(obj1) : [];
        const keys2 = typeof obj2 === 'object' ? Object.keys(obj2) : [];
        const allKeys = new Set([...keys1, ...keys2]);
        
        for (const key of allKeys) {
            const currentPath = path ? `${path}.${key}` : key;
            const val1 = obj1 && typeof obj1 === 'object' ? obj1[key] : undefined;
            const val2 = obj2 && typeof obj2 === 'object' ? obj2[key] : undefined;
            
            if (val1 === undefined) {
                diffs.push({
                    type: 'added',
                    path: currentPath,
                    newValue: val2,
                    valueType: this.getValueType(val2)
                });
            } else if (val2 === undefined) {
                diffs.push({
                    type: 'removed',
                    path: currentPath,
                    oldValue: val1,
                    valueType: this.getValueType(val1)
                });
            } else if (this.isObject(val1) && this.isObject(val2)) {
                // 递归比较对象
                diffs.push(...this.computeDiff(val1, val2, currentPath));
            } else if (this.isArray(val1) && this.isArray(val2)) {
                // 递归比较数组
                diffs.push(...this.computeArrayDiff(val1, val2, currentPath));
            } else if (val1 !== val2) {
                diffs.push({
                    type: 'modified',
                    path: currentPath,
                    oldValue: val1,
                    newValue: val2,
                    oldValueType: this.getValueType(val1),
                    newValueType: this.getValueType(val2)
                });
            }
        }
        
        return diffs;
    }
    
    /**
     * 计算两个数组之间的差异
     * @param {Array} arr1 - 第一个数组
     * @param {Array} arr2 - 第二个数组
     * @param {string} path - 当前路径
     * @returns {Array} 差异数组
     */
    static computeArrayDiff(arr1, arr2, path) {
        const diffs = [];
        
        // 简单实现：比较相同索引的元素
        const maxLength = Math.max(arr1.length, arr2.length);
        for (let i = 0; i < maxLength; i++) {
            const currentPath = `${path}[${i}]`;
            const val1 = arr1[i];
            const val2 = arr2[i];
            
            if (val1 === undefined) {
                diffs.push({
                    type: 'added',
                    path: currentPath,
                    newValue: val2,
                    valueType: this.getValueType(val2)
                });
            } else if (val2 === undefined) {
                diffs.push({
                    type: 'removed',
                    path: currentPath,
                    oldValue: val1,
                    valueType: this.getValueType(val1)
                });
            } else if (this.isObject(val1) && this.isObject(val2)) {
                // 递归比较对象
                diffs.push(...this.computeDiff(val1, val2, currentPath));
            } else if (this.isArray(val1) && this.isArray(val2)) {
                // 递归比较数组
                diffs.push(...this.computeArrayDiff(val1, val2, currentPath));
            } else if (val1 !== val2) {
                diffs.push({
                    type: 'modified',
                    path: currentPath,
                    oldValue: val1,
                    newValue: val2,
                    oldValueType: this.getValueType(val1),
                    newValueType: this.getValueType(val2)
                });
            }
        }
        
        return diffs;
    }
    
    /**
     * 判断是否为对象
     * @param {*} value - 要判断的值
     * @returns {boolean}
     */
    static isObject(value) {
        return value !== null && typeof value === 'object' && !Array.isArray(value);
    }
    
    /**
     * 判断是否为数组
     * @param {*} value - 要判断的值
     * @returns {boolean}
     */
    static isArray(value) {
        return Array.isArray(value);
    }
    
    /**
     * 获取值的类型
     * @param {*} value - 要判断的值
     * @returns {string}
     */
    static getValueType(value) {
        if (value === null) return 'null';
        if (Array.isArray(value)) return 'array';
        return typeof value;
    }
    
    /**
     * 深度比较两个对象是否相等
     * @param {*} obj1 - 第一个对象
     * @param {*} obj2 - 第二个对象
     * @returns {boolean}
     */
    static deepEqual(obj1, obj2) {
        return JSON.stringify(this.normalizeData(obj1)) === JSON.stringify(this.normalizeData(obj2));
    }
    
    /**
     * 标准化数据，确保比较的准确性
     * @param {*} data - 要标准化的数据
     * @returns {*} 标准化后的数据
     */
    static normalizeData(data) {
        if (data === null || data === undefined) {
            return data;
        }
        
        if (typeof data !== 'object') {
            return data;
        }
        
        if (Array.isArray(data)) {
            return data.map(item => this.normalizeData(item));
        }
        
        // 对对象的键进行排序，确保比较的一致性
        const normalized = {};
        Object.keys(data).sort().forEach(key => {
            normalized[key] = this.normalizeData(data[key]);
        });
        
        return normalized;
    }
}

// 导出类
if (typeof module !== 'undefined' && module.exports) {
    module.exports = JSONDiffEngine;
}